package com.rockwell.sniffyHunter.test;

import java.util.HashMap;
import java.util.Map;

import junit.framework.Assert;

import android.annotation.SuppressLint;

import com.rockwell.sniffyhunter.model.LeftFirstMazeSolver;
import com.rockwell.sniffyhunter.model.Robot;
import com.rockwell.sniffyhunter.model.StatefulRobot;
import com.rockwell.sniffyhunter.utils.DetectionIndex;
import com.rockwell.sniffyhunter.utils.IDetector;
import com.rockwell.sniffyhunter.utils.IMazeSolver;
import com.rockwell.sniffyhunter.utils.IRobotCommander;
import com.rockwell.sniffyhunter.utils.RobotState;

public class RobotStateTester extends UnitTestLooper {
	private FakeRobotSensors		sensor;
	private Map<Integer, IDetector>	colorDetectors;
	private FakeColorDetector		maze3Detector;
	private FakeTreasureDetector	treasureDetector;
	private IRobotCommander 		robotCommander;
	private FakeTreasureCollector 	treasureCollector;
	private Robot 					robot; 
	private StatefulRobot 			statefulRobot;
	IMazeSolver 					solver;
	
	@SuppressLint("UseSparseArrays") @SuppressWarnings("serial")
	@Override
	public void setUp() {
		solver 				= new LeftFirstMazeSolver();
		sensor 				= new FakeRobotSensors();
		treasureDetector	= new FakeTreasureDetector();
		maze3Detector		= new FakeColorDetector();
		colorDetectors 		= new HashMap<Integer, IDetector>() {
							  {
								  put(DetectionIndex.TREASURE, treasureDetector);
								  put(DetectionIndex.OBSTACLE, new FakeColorDetector()/*obstacle detector*/); 
								  put(DetectionIndex.MAZE1, new FakeColorDetector()/*maze1 detector*/);
								  put(DetectionIndex.MAZE2, new FakeColorDetector()/*maze2 detector*/);
								  put(DetectionIndex.MAZE3, maze3Detector/*maze3 detector*/);
								  put(DetectionIndex.DROPZONE, new FakeColorDetector()/*dropZone detector*/);
								  put(DetectionIndex.MAZE_EXIT, new FakeColorDetector()/*dropZone detector*/);
							  }};
		robotCommander 		= new DummyRobotCommander();
		treasureCollector 	= new FakeTreasureCollector();
		robot 				= new Robot(0, 0, 
								1 /*start Zone*/,
								sensor, 
								robotCommander, 
								null/*maze*/, 
								solver/*solver*/, 
								colorDetectors, 
								treasureCollector);
		statefulRobot 		= new StatefulRobot(robot);
	}
	
	@Override
	public void tearDown() {

	}
	
	public void testSniffAndMoveToNextZone() {
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.START);
		
		statefulRobot.PerformAction();
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.SNIFF);
		
		loopUntilCondition(statefulRobot, RobotState.MOVE_TO_NEXT_ZONE);
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.MOVE_TO_NEXT_ZONE);
		
		loopUntilCondition(statefulRobot, RobotState.SNIFF);
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.SNIFF);
	}
	
	public void testSniffAndPick() {
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.START);
		
		statefulRobot.PerformAction();
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.SNIFF);

		treasureDetector.m_isPresent = true;
		loopUntilCondition(statefulRobot, RobotState.PICK_TREASURE);
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.PICK_TREASURE);
		
		statefulRobot.PerformAction();
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.PICK_TREASURE);
		
		loopUntilCondition(statefulRobot, RobotState.SNIFF);
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.SNIFF);
	}
	
	public void testSniffAndUnload() {
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.START);
		
		treasureCollector.m_isFull = true;
		statefulRobot.PerformAction();
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.SNIFF);
		
		sensor.setFrontWallOnTimeout(5);
		maze3Detector.m_present = true;
		loopUntilCondition(statefulRobot, RobotState.UNLOAD);
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.UNLOAD);

		sensor.setLeftWallOnTimeout(5);
		sensor.setRightWallOnTimeout(5);
		loopUntilCondition(statefulRobot, RobotState.SNIFF);
		Assert.assertEquals(statefulRobot.getStateMachine(), RobotState.SNIFF);
	}
}
